package cn.cutie.clotcache.core;

import java.util.*;

/**
 * @Description: 缓存
 * @Author: Cutie
 * @CreateDate: 2024/6/15 20:11
 * @Version: 0.0.1
 */
public class ClotCache {

//    @Getter
//    private static ClotCache instance = new ClotCache();

    Map<String, CacheEntry<?>> map = new HashMap<>();
    public String get(String key) {
        CacheEntry<String> cacheEntry = (CacheEntry<String>) map.get(key);
        return cacheEntry.getValue();
    }

    public void set(String key, String value) {
        map.put(key, new CacheEntry<>(value));
    }

    public int del(String... keys) {
        return keys == null ? 0 : (int)Arrays.stream(keys).map(map::remove).filter(s -> s != null).count();
    }

    public int exists(String... keys){
        return keys == null ? 0 : (int)Arrays.stream(keys).map(map::containsKey).filter(s -> s == true).count();
//        return keys == null ? 0 : (int)Arrays.stream(keys).filter(s -> map.containsKey(s)).count();
    }

    public String[] mget(String... keys) {
        return keys == null ? new String[0] : Arrays.stream(keys).map(this::get).toArray(String[]::new);
    }

    public void mset(String[] keys, String[] values) {
        if (keys == null || values == null) return;
        for (int i = 0; i < keys.length; i++){
            set(keys[i], values[i]);
        }
    }

    public int incr(String key) {
        String str = get(key);
        int val = 0;
        try{
            if (str != null){
                val = Integer.parseInt(str);
            }
            val++;
            set(key, String.valueOf(val));
        } catch (NumberFormatException e){
            throw e;
        }
        return val;
    }

    public int decr(String key) {
        String str = get(key);
        int val = 0;
        try{
            if (str != null){
                val = Integer.parseInt(str);
            }
            val--;
            set(key, String.valueOf(val));
        } catch (NumberFormatException e){
            throw e;
        }
        return val;
    }

    public Integer strLen(String key) {
        return get(key) == null ? 0 : get(key).length();
    }

    public int lpush(String key, String[] values) {
        CacheEntry<LinkedList<String>> entry = (CacheEntry<LinkedList<String>>) map.get(key);
        if(entry == null) {
            entry = new CacheEntry<>(new LinkedList<>());
            this.map.put(key, entry);
        }
        LinkedList<String> exist = entry.getValue();
        Arrays.stream(values).forEach(exist::addFirst);
        return values.length;
    }

    public String[] lpop(String key, int count) {
        CacheEntry<LinkedList<String>> entry = (CacheEntry<LinkedList<String>>) map.get(key);
        if(entry == null) return null;
        LinkedList<String> exist = entry.getValue();
        if(exist == null) return null;
        int len = Math.min(count, exist.size());
        String[] ret = new String[len];
        int index = 0;
        while(index < len) {
            ret[index ++] = exist.removeFirst();
        }
        return ret;
    }

    public int rpush(String key, String[] vals) {
        CacheEntry<LinkedList<String>> entry = (CacheEntry<LinkedList<String>>) map.get(key);
        if(entry == null) {
            entry = new CacheEntry<>(new LinkedList<>());
            this.map.put(key, entry);
        }
        LinkedList<String> exist = entry.getValue();
//        Arrays.stream(vals).forEach(exist::addLast);
        exist.addAll(List.of(vals));
        return vals.length;
    }

    public String[] rpop(String key, int count) {
        CacheEntry<LinkedList<String>> entry = (CacheEntry<LinkedList<String>>) map.get(key);
        if(entry == null) return null;
        LinkedList<String> exist = entry.getValue();
        if(exist == null) return null;
        int len = Math.min(count, exist.size());
        String[] ret = new String[len];
        int index = 0;
        while(index < len) {
            ret[index ++] = exist.removeLast();
        }
        return ret;
    }

    public int llen(String key) {
        CacheEntry<LinkedList<String>> entry = (CacheEntry<LinkedList<String>>) map.get(key);
        if (entry == null) return 0;
        LinkedList<String> exist = entry.getValue();
        if (exist == null) return 0;
        return exist.size();
    }

    public String lindex(String key, int index) {
        CacheEntry<LinkedList<String>> entry = (CacheEntry<LinkedList<String>>) map.get(key);
        if (entry == null) return null;
        LinkedList<String> exist = entry.getValue();
        if (exist == null) return null;
        if(index >= exist.size()) return null;
        return exist.get(index);
    }

    public String[] lrange(String key, int start, int end) {
        CacheEntry<LinkedList<String>> entry = (CacheEntry<LinkedList<String>>) map.get(key);
        if (entry == null) return null;
        LinkedList<String> exist = entry.getValue();
        if (exist == null) return null;
        int size = exist.size();
        if(start >= size) return null;
        if(end >= size) end = size - 1;
        int len = Math.min(size, end - start + 1);
        String[] ret = new String[len];
        for(int i=0;i<len;i++) {
            ret[i] = exist.get(start + i);
        }
        return ret;
    }
}
